'use strict';

if (zxcv && !zxcv.ShaderEffect) {
    zxcv.ShaderEffect = function (name, vertexCode, fragmentCode, defines) {
        var i, length,
            codePrefix,
            gl = zxcv.raw.graphics.gl,
            vertexShader,
            fragmentShader,
            program,
            attributes,
            uniforms;

        if (defines) {
            codePrefix = '';
            for (i = 0, length = defines.length; i < length; i++) 
                codePrefix += '#define ' + defines[i] + '\n';

            vertexCode   = codePrefix + vertexCode;
            fragmentCode = codePrefix + fragmentCode;
        }

        vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, vertexCode);
        gl.compileShader(vertexShader);
        if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
            throw new Error('vertex shader compile failed. ' + gl.getShaderInfoLog(vertexShader));

        fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, fragmentCode);
        gl.compileShader(fragmentShader);
        if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
            throw new Error('fragment shader compile failed. ' + gl.getShaderInfoLog(fragmentShader));

        program = gl.createProgram();
        gl.attachShader(program, vs);
        gl.attachShader(program, fs);
        gl.linkProgram(program);
        if (!gl.getProgramParameter(program, gl.LINK_STATUS))
            throw new Error('program link failed. ' + gl.getProgramInfoLog(program));

        attributes = {
            VPosition: gl.getAttribLocation(program, 'VPosition'),
            VTexture1: gl.getAttribLocation(program, 'VTexture1'),
            VTexture2: gl.getAttribLocation(program, 'VTexture2'),
            VColor:    gl.getAttribLocation(program, 'VColor'),
        };
        uniforms = {
            World:      gl.getUniformLocation(program, 'World'),
            Projection: gl.getUniformLocation(program, 'Projection'),
            Sampler1:   gl.getUniformLocation(program, 'Sampler1'),
            Sampler2:   gl.getUniformLocation(program, 'Sampler2'),
        };
        
        this.name = name || '';
        this.vs = vertexShader;
        this.fs = fragmentShader;
        this.raw = program;
        this.attributes = attributes;
        this.uniforms = uniforms;
    }
}